#pragma once

#include <limits>
#include <string>
#include <unordered_map>
#include <blu\types.h>
#include <teresa\impl\common.h>

namespace teresa
{
	typedef unsigned vertex_semantic_size_t;

	class vertex_semantic;

	namespace impl
	{
		vertex_semantic _make_var_semantic(vertex_semantic_size_t index_, blu::type_identity type_);
	}

	class vertex_semantic
	{
		friend vertex_semantic impl::_make_var_semantic(vertex_semantic_size_t index_, blu::type_identity type_);

		template <typename>
		friend struct std::hash;
	private:
		vertex_semantic_size_t _id;
		blu::type_identity _type;

		vertex_semantic(
			vertex_semantic_size_t index_,
			blu::type_identity type_)
			:_id(index_), _type(type_)
		{

		}
	public:
		blu::type_identity type() const
		{
			return _type;
		}

		bool operator==(const vertex_semantic &that) const
		{
			return _id == that._id;
		}

		bool operator!=(const vertex_semantic &that) const
		{
			return !(*this == that);
		}
	};

	TERESA_EXPORT extern vertex_semantic predefined_semantic_postition_3d;
	TERESA_EXPORT extern vertex_semantic predefined_semantic_normal_3d;
	TERESA_EXPORT extern vertex_semantic predefined_semantic_texcoord_2d;
	TERESA_EXPORT extern vertex_semantic predefined_semantic_joint_index;
	TERESA_EXPORT extern vertex_semantic predefined_semantic_joint_weight;

	class vertex_semantic_counter
	{
	private:
		std::unordered_map<std::string, vertex_semantic> _samMap;
		void _addPredefines()
		{

		}
	public:
		vertex_semantic_counter()
		{
			_addPredefines();
		}
	};
}

namespace std
{
	template <>
	struct hash<teresa::vertex_semantic>
	{
		std::size_t operator()(const teresa::vertex_semantic &v) const
		{
			return std::hash<decltype(v._id)>()(v._id);
		}
	};
}